﻿using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using Quail;
using QuailDashboard.View.Converters;
using QuailDashboard.View.Data;

namespace QuailDashboard.View.QuailServiceReference
{
    /// <summary>
    /// Extensions ot the GetRunStatusResult model
    /// </summary>
    public partial class GetRunStatusResult
    {
        private LogEntries _logEntries;
        private ObservableCollection<TestNote> _testnotes;
        private bool _isChecked;
        private bool _isExecuting, _isExecutingNewTest;
        private DateTime? _calculatedDuration;

        /// <summary>
        /// Gets or sets a value indicating whether this test is selected.
        /// </summary>
        /// <value>
        /// 	<c>true</c> if this test is selected; otherwise, <c>false</c>.
        /// </value>
        public bool IsChecked
        {
            get
            {
                return _isChecked;
            }
            set
            {
                if (_isChecked != value)
                {
                    _isChecked = value;
                    RaisePropertyChanged("IsChecked");
                }
            }
        }


        /// <summary>
        /// Gets the duration as calculated by the dashboard
        /// </summary>
        public DateTime? CalculatedDuration
        {
            get
            {
                if (_calculatedDuration.HasValue)
                    return _calculatedDuration;

                if (!IsPending)
                    return Duration;

                return _calculatedDuration;   
            }

            set
            {
                _calculatedDuration = value;
                RaisePropertyChanged("CalculatedDuration");
            }
        }

        /// <summary>
        /// Gets or sets a value indicating whether this test is in a pending state.
        /// </summary>
        /// <value>
        /// 	<c>true</c> if this test is pending; otherwise, <c>false</c>.
        /// </value>
        public bool IsPending
        {
            get
            {
                return RunStatusId == (int) LogStatus.Pending;
            }
        }

        /// <summary>
        /// Gets or sets a value indicating whether this async test is in a pending state.
        /// </summary>
        /// <value>
        /// 	<c>true</c> if this async test is pending; otherwise, <c>false</c>.
        /// </value>
        public bool IsAsyncPending
        {
            get
            {
                return RunStatusId == (int) LogStatus.AsyncPending;
            }
        }

        /// <summary>
        /// Gets or sets a value indicating whether this test is executing.
        /// </summary>
        /// <value>
        /// 	<c>true</c> if this test is executing; otherwise, <c>false</c>.
        /// </value>
        public bool IsExecuting
        {
            get
            {
                return _isExecuting;
            }
            set
            {
                if (_isExecuting != value)
                {
                    _isExecuting = value;
                    RaisePropertyChanged("IsExecuting");
                }
            }
        }

        public bool IsExecutingNewTest
        {
            get
            {
                return _isExecutingNewTest;
            }
            set
            {
                if (_isExecutingNewTest != value)
                {
                    _isExecutingNewTest = value;
                    RaisePropertyChanged("IsExecutingNewTest");
                }
            }            
        }

        /// <summary>
        /// Gets the full name of the test, including class name
        /// </summary>
        public string FullName
        {
            get
            {
                return CompleteTestClassName + "." + TestName;
            }
        }

        /// <summary>
        /// Gets the test class name
        /// </summary>
        public string CompleteTestClassName
        {
            get
            {
                return TestClassName ?? "Unknown";
            }
        }

        /// <summary>
        /// Gets the test notes for this test run data
        /// </summary>
        public ObservableCollection<TestNote> TestNotes
        {
            get
            {
                if (_testnotes == null)
                    _testnotes = new ObservableCollection<TestNote>();

                return _testnotes;
            }
        }

        /// <summary>
        /// Gets all the log entries for this test run data
        /// </summary>
        public LogEntries AllLogEntries
        {
            get
            {
                if (_logEntries == null)
                    _logEntries = new LogEntries();

                return _logEntries;
            }
        }

        /// <summary>
        /// TestRunData comparer class
        /// </summary>
        public class TestRunDataComparer : IEqualityComparer<GetRunStatusResult>
        {
            /// <summary>
            /// Determines whether the specified objects are equal.
            /// </summary>
            /// <returns>
            /// true if the specified objects are equal; otherwise, false.
            /// </returns>
            /// <param name="x">The first object of type TestRunData to compare.</param>
            /// <param name="y">The second object of type TestRunData to compare.</param>
            public bool Equals(GetRunStatusResult x, GetRunStatusResult y)
            {
                return x.TestEnvironmentId == y.TestEnvironmentId && x.FullName == y.FullName;
            }

            /// <summary>
            /// Returns a hash code for the specified object.
            /// </summary>
            /// <returns>
            /// A hash code for the specified object.
            /// </returns>
            /// <param name="obj">The <see cref="T:System.Object"/> for which a hash code is to be returned.</param>
            /// <exception cref="T:System.ArgumentNullException">The type of <paramref name="obj"/> is a reference type and <paramref name="obj"/> is null.</exception>
            public int GetHashCode(GetRunStatusResult obj)
            {
                return obj.FullName.GetHashCode() + obj.TestEnvironmentId;
            }
        }
    }
}